package cn.karent.app;

import cn.karent.client.api.CookApi;
import cn.karent.client.dto.CategoryCook;
import cn.karent.client.dto.SearchResp;
import cn.karent.common.Pageable;
import cn.karent.common.Result;
import cn.karent.domain.Cook;
import cn.karent.domain.LuceneIndexService;
import cn.karent.domain.SearchContent;
import cn.karent.infra.CookMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author wanshengdao
 * @date 2025/4/15
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class CookApiImpl implements CookApi {

    private final LuceneIndexService luceneIndexService;

    private final CookMapper cookMapper;

    @Override
    public void publish(String category, String name, String content) {
        Cook cook = Cook.builder()
                .name(name)
                .category(category)
                .content(content)
                .build();
        cookMapper.insert(cook);
        // 写入lucene
        luceneIndexService.addDocumentToIndex(cook);
    }

    @Override
    public Pageable<SearchResp> search(String value, Integer page, Integer num) {
        try {
            Pageable<SearchContent> content = luceneIndexService.search(value, page, num);
            return Pageable.transfer(content, SearchRespTransfer.INSTANCE::toSearchResp);
        } catch (Exception e) {
            throw new IllegalStateException("查询异常", e);
        }
    }


    @Override
    public Result<List<CategoryCook>> list() {
        LambdaQueryWrapper<Cook> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Cook::getCategory, Cook::getName, Cook::getId);
        List<Cook> cooks = cookMapper.selectList(wrapper);
        Map<String, List<Cook>> map = cooks.stream().collect(Collectors.groupingBy(Cook::getCategory));
        List<CategoryCook> categoryCooks = map.entrySet().stream().map(entry -> {
            CategoryCook categoryCook = new CategoryCook();
            categoryCook.setCategory(entry.getKey());
            categoryCook.setCookings(entry.getValue());
            return categoryCook;
        }).toList();
        return Result.ok(categoryCooks);
    }

    @Override
    public Result<Cook> get(Integer id) {
        Cook cook = cookMapper.selectById(id);
        Assert.notNull(cook, "菜谱不存在");
        return Result.ok(cook);
    }

    @Override
    public void delete(Integer id) {
        // 删除lucene
        luceneIndexService.deleteDocument(id);
        // 删除数据库
        cookMapper.deleteById(id);
    }

    @Override
    public void update(Integer id, String category, String name, String content) {
        Cook cook = buildCook(id, category, name, content);
        // 更新lucene
        luceneIndexService.updateDocument(cook);
        // 更新数据库
        cookMapper.updateById(cook);
    }

    private Cook buildCook(Integer id, String category, String name, String content) {
        Cook oldCook = cookMapper.selectById(id);
        category = Optional.ofNullable(category).orElse(oldCook.getCategory());
        name = Optional.ofNullable(name).orElse(oldCook.getName());
        content = Optional.ofNullable(content).orElse(oldCook.getContent());
        return Cook.builder()
                .id(id)
                .category(category)
                .name(name)
                .content(content)
                .build();
    }
}
